﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace MetaDemo.Metrics
{
    public class AssemblyAnalyzer
    {


        private Dictionary<string, int> dict = new Dictionary<string, int>();
        private KeyValuePair<Type, int> maxLeaf;

        private int typeCount = 0;
        private int methodCount = 0;

        private int maxInheritanceDepth = 0;
        private Type maxInheritanceDepthType = typeof(Nullable);
        private int avgMethodCountPerClass = 0;

        public int MaxInheritanceDepth { get { return maxInheritanceDepth; } }
        public Type MaxInheritanceDepthType { get { return maxInheritanceDepthType; } }
        public int AvgMethodCountPerClass { get { return avgMethodCountPerClass; } }

        public AssemblyAnalyzer(Assembly assembly)
        {
            foreach (Module module in assembly.GetModules(false))
            {
                foreach (Type type in module.GetTypes())
                {
                    if (!type.IsInterface &&
                            !type.IsEnum &&
                            !type.IsGenericParameter &&
                            !type.IsGenericType &&
                            !type.IsArray &&
                            !type.IsPointer)
                    {

                        // 1) max. Vererbungstiefe berechnen
                        AddToInheritanceTreeComp(type);

                        // 2) durchschnittliche Zahl von Methoden berechnen
                        AddToAvgMethodComp(type);
                    }
                }
            }

            maxInheritanceDepth = maxLeaf.Value;
            maxInheritanceDepthType = maxLeaf.Key;
            avgMethodCountPerClass = (int)((float)methodCount / (float)typeCount);
        }

        private void AddToInheritanceTreeComp(Type type)
        {
            Type baseType = type.BaseType;
            if (baseType == null)
            {
                dict.Add(type.FullName, 0);
                maxLeaf = new KeyValuePair<Type, int>(type, 0);

            }
            else
            {
                if (!dict.ContainsKey(baseType.FullName))
                {
                    AddToInheritanceTreeComp(baseType);
                }
                int numberOfBaseTypes = dict[baseType.FullName] + 1;
                dict.Add(type.FullName, numberOfBaseTypes);
                if (numberOfBaseTypes > maxLeaf.Value)
                {
                    maxLeaf = new KeyValuePair<Type, int>(type, numberOfBaseTypes);
                }
            }
        }

        private void AddToAvgMethodComp(Type type)
        {
            typeCount++;
            methodCount += type.GetMethods(
                BindingFlags.Public |
                BindingFlags.NonPublic |
                BindingFlags.Static |
                BindingFlags.Instance
            ).Length;
        }
    }
}